package serverAndThreads;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.*;
import java.sql.SQLException;
import databas.User_DB;

import staticClasses.F;
import staticClasses.Port;

/* Author Jerry & Mats */
public class Server {
	ST[] st = new ST[F.AMOUNT];

	public Server() {
		new User_DB().setEveryoneOffline();
		declareAbstractMethods();

		// new ChatServer();

		newServerThread();
		System.out.println("Server is up and running!");
	}

	private void newServerThread() {
		new Thread(new ServerThread()).start();
	}

	private ST[] declareAbstractMethods() {
		st[F.NEW_USER] = new ST.NewUser();
		st[F.CREATE_GROUP] = new ST.CreateGroup();
		st[F.GET_CONTACT_LIST] = new ST.ContacList();
		st[F.LOGIN] = new ST.LoginUser();
		st[F.GET_GROUP_LIST] = new ST.GroupList();
		st[F.LOGOUT] = new ST.LogOutUser();
		st[F.ADD_CONTACT] = new ST.AddContact();
		st[F.REMOVE_CONTACT] = new ST.RemoveContact();
		st[F.UPDATE_GROUP] = new ST.UpdateGroup();
		st[F.SAVE_STICKY_NOTE] = new ST.SaveStickyNote();
		st[F.GET_STICKY_NOTE] = new ST.GetStickyNote();
		st[F.REMOVE_STICKY_NOTE] = new ST.RemoveStickyNote();
		st[F.SEARCH_USER] = new ST.SearchUser();
		st[F.START_CHAT] = new ST.StartChat();
		st[F.CHAT_MESSAGE] = new ST.ChatMessage();
		st[F.USER_LEAVING_CHAT] = new ST.UserLeavingChat();
		st[F.GROUP_MESSAGE] = new ST.SendGroupMessage();
		return st;
	}

	public class ServerThread implements Runnable {

		@Override
		public void run() {
			try {
				// Ger tillbaka en array med abstrakta metoder som kommer att
				// anv锟絥das senare

				ServerSocket serverSocket = new ServerSocket(
						Port.getServerPort());

				Socket socket = serverSocket.accept();

				/**
				 * Nu n锟絩 en socket har skapats s锟�st锟絥gs serversocket till
				 * ServerPort s锟�att en ny kan 锟絧pnas
				 */
				serverSocket.close();
				newServerThread();
				/**
				 * When a new message comes in, starts a new thread that keeps
				 * on listening for more
				 */

				ObjectInputStream in = new ObjectInputStream(
						socket.getInputStream());
				ObjectOutputStream out = new ObjectOutputStream(
						socket.getOutputStream());

				/**
				 * N锟絩 den deklareras 锟絩 det bara att anropa dess abstrakta
				 * metod: perform, s锟�kommer den 锟絥skade metoden att utf锟絩as
				 */

				int function = (Integer) in.readObject();
				st[function].perform(in, out);

				// Close connections
				in.close();
				out.close();
				socket.close();

			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}

		/**
		 * Kan anv锟絥das ifall det inte fungerar att skicka abstracta object...
		 * 
		 * @param function
		 * @return
		 */

	}

	public static void main(String[] args) throws IOException {
		new Server();
	}

}
